#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include<sys/types.h>
#include<sys/socket.h>
#include <jsoncpp/json/json.h>

#include "Util.hpp"

// #define MYSELF 1

namespace protocol_ns
{
#define SEP " " // 分隔符
#define SEP_LEN strlen(SEP)
#define HEADER_SEP "\r\n" // 报头分隔符
#define HEADER_SEP_LEN strlen(HEADER_SEP)

    // 添加报头
    std::string AddHead(const std::string &str)
    {
        std::string res;
        res = std::to_string(str.size()) + HEADER_SEP + str + HEADER_SEP;
        return res;
    }

    // 去除报头，提取有效载荷
    std::string RemoveHead(int len, const std::string &package)
    {
        return package.substr(package.size() - len - HEADER_SEP_LEN, len);
    }

    // 读取数据，并尝试提取一个完整报文
    // 完整报文："有效载荷长度""\r\n""有效载荷""\r\n"
    int ParsePackage(std::string &inbuffer, std::string *package)
    {
        size_t start = 0;
        auto pos = inbuffer.find(HEADER_SEP, start);
        if (pos == std::string::npos)
            return 0; // 没有完整报文

        std::string lenStr = inbuffer.substr(0, pos);
        int len = Util::toInt(lenStr); // 有效载荷的长度
        // 完整报文的长度
        int targetPackageLen = lenStr.size() + len + 2 * HEADER_SEP_LEN;
        if (inbuffer.size() < targetPackageLen)
            return 0; // 没有完整报文
        // 提取一个完整报文
        *package = inbuffer.substr(0, targetPackageLen);
        inbuffer.erase(0, targetPackageLen);

        return len;
    }
    // 请求
    class Request
    {
    public:
        Request() {}

        // 结构体=>字符串
        bool Serialize(std::string *outStr)
        {
#ifdef MYSELF
            *outStr = "";
            std::string x_string = std::to_string(_x);
            std::string y_string = std::to_string(_y);
            *outStr = x_string + SEP + _op + SEP + y_string;
#else
            // Value，一种万能对象，接收任意的kv类型
            Json::Value root;
            root["x"] = _x;
            root["y"] = _y;
            root["op"] = _op;
            // 序列化
            Json::StyledWriter writer;
            *outStr = writer.write(root);
#endif

            return true;
        }
        // 字符串=>结构体
        bool Deserialize(const std::string &str)
        {
#ifdef MYSELF
            std::vector<std::string> result;
            Util::StringSplit(str, SEP, &result);
            if (result.size() != 3)
                return false;
            if (result[1].size() != 1)
                return false;

            _x = Util::toInt(result[0]);
            _op = result[1][0];
            _y = Util::toInt(result[2]);
#else
            Json::Value root;
            // 反序列化
            Json::Reader reader;
            reader.parse(str, root);

            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _op = root["op"].asInt();
#endif
            return true;
        }

    public:
        int _x;
        int _y;
        char _op;
    };
    // 响应
    class Responce
    {
    public:
        Responce() : _result(0), _code(0)
        {
        }

        // 结构体->字符串
        bool Serialize(std::string *outStr)
        {
#ifdef MYSELF
            *outStr = "";
            std::string result_string = std::to_string(_result);
            std::string code_string = std::to_string(_code);
            *outStr = result_string + SEP + code_string;
#else
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;

            // 序列化
            Json::StyledWriter writer;
            *outStr = writer.write(root);
#endif
            return true;
        }

        bool Deserialize(const std::string &str)
        {
#ifdef MYSELF
            std::vector<std::string> result;
            Util::StringSplit(str, SEP, &result);
            if (result.size() != 2)
                return false;

            _result = Util::toInt(result[0]);
            _code = Util::toInt(result[1]);
#else
            Json::Value root;
            Json::Reader reader;
            reader.parse(str, root);

            _result = root["result"].asInt();
            _code = root["code"].asInt();
#endif
            return true;
        }

    public:
        int _result;
        int _code;
    };
}


